#include "Descarga.h"

Descarga::Descarga(int idUsuarioComparte, string pathArchivo, int idUsuarioDescarga) {
	solicitud.idUsuarioComparte = idUsuarioComparte;
	strcpy(solicitud.pathArchivo, pathArchivo.c_str());
	solicitud.idUsuarioDescarga = idUsuarioDescarga;
}

Descarga::Descarga(int idUsuarioComparte, int idUsuarioDescarga) {
	solicitud.idUsuarioComparte = idUsuarioComparte;
	solicitud.pathArchivo[0] = '\0';
	solicitud.idUsuarioDescarga = idUsuarioDescarga;
}

Descarga::~Descarga() {
}

void Descarga::ejecutar() {
	// TODO: Refactorizar en metodos mas pequeños.
	// TODO: aplicar protocolo de inicio y fin de archivo. controlar size.
	strcpy(solicitud.idDescarga, toString(solicitud.idUsuarioDescarga).append(toString(time(0))).c_str());
	stringstream sstream;
	sstream << "Inicializando descarga. Solicitante: " << solicitud.idUsuarioDescarga << ";  Solicitado: " << solicitud.idUsuarioComparte << ";  Id descarga: " << solicitud.idDescarga;
	Log::getInstance()->log(sstream.str());
	Entorno::getInstance()->solicitarDescarga(solicitud);
	kill(this->solicitud.idUsuarioComparte, UPLOAD_SIGNAL);

	// leo el FIFO de transferencia
	string fifoFile = FIFO_DESCARGA_PATH;
	fifoFile += this->solicitud.idDescarga;
	Fifo canal (fifoFile.c_str());
	char buffer[BUFFER_MAX];

	string contenido = "";
	int bytesLeidos = 0;
	do {
		bytesLeidos = canal.leer(buffer,BUFFER_MAX);
		if (bytesLeidos < BUFFER_MAX){
			buffer[bytesLeidos] = '\0';
		}
		contenido.append(buffer,bytesLeidos);
	} while (bytesLeidos == BUFFER_MAX);

	canal.cerrar();

	// Obtengo path de descarga
	string path = Usuario::getInstance()->getCarpetaDescarga();
	path += getFileName(this->solicitud.pathArchivo);

	// si ya existe el archivo a descargar, renombro la descarga
	if (fileExists(path)) {
		path.append("_");
		path.append(solicitud.idDescarga);
	}

	// guardo el buffer leido del FIFO en el archivo descargado.
	fstream stream;
	stream.open (path.c_str(), fstream::out | fstream::app);
	stream << contenido;
	stream.flush();
	stream.close();
	stringstream logstream;
	logstream << "Descarga finalizada. Solicitante: " << solicitud.idUsuarioDescarga << ";  Solicitado: " << solicitud.idUsuarioComparte << ";  Id descarga: " << solicitud.idDescarga;
	Log::getInstance()->log(logstream.str());
}

list<string> Descarga::verArchivosCompartidos() {
	solicitud.pathArchivo[0] = '\0';
	strcpy(solicitud.idDescarga, toString(solicitud.idUsuarioDescarga).append(toString(time(0))).c_str());

	stringstream sstream;
	sstream << "Solicitando listado archivos. Solicitante: " << solicitud.idUsuarioDescarga << ";  Solicitado: " << solicitud.idUsuarioComparte << ";  Id solicitud: " << solicitud.idDescarga;
	Log::getInstance()->log(sstream.str());
	Entorno::getInstance()->solicitarDescarga(solicitud);
	kill(this->solicitud.idUsuarioComparte, PUBLISH_FILES_SIGNAL);

	// leo el FIFO de transferencia
	string fifoFile = FIFO_DESCARGA_PATH;
	fifoFile += this->solicitud.idDescarga;
	Fifo canal (fifoFile.c_str());
	char buffer[BUFFER_MAX];

	string contenido = "";
	int bytesLeidos = 0;
	do {
		bytesLeidos = canal.leer(buffer,BUFFER_MAX);
		if (bytesLeidos < BUFFER_MAX){
			buffer[bytesLeidos] = '\0';
		}
		contenido.append(buffer,bytesLeidos);
	} while (bytesLeidos == BUFFER_MAX);

	canal.cerrar();

	list<string> listaArchivos;

	int begin = 0;
	int end = contenido.find_first_of('\n',begin);
	while (end > 0) {
		listaArchivos.push_back(contenido.substr(begin,end-begin));
		begin = end+1;
		end = contenido.find_first_of('\n',begin);
	}
	stringstream logstream;
	logstream << "Listado de archivos obtenido. Solicitante: " << solicitud.idUsuarioDescarga << ";  Solicitado: " << solicitud.idUsuarioComparte << ";  Id solicitud: " << solicitud.idDescarga;
	Log::getInstance()->log(logstream.str());
	return listaArchivos;
}
